package org.ragdollcat.first.manager.auth;

import cn.dev33.satoken.stp.StpInterface;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.ragdollcat.first.constants.UserConstant;
import org.ragdollcat.first.exception.ErrorCode;
import org.ragdollcat.first.exception.ThrowUtils;
import org.ragdollcat.first.model.entity.Picture;
import org.ragdollcat.first.model.entity.Space;
import org.ragdollcat.first.model.entity.SpaceUser;
import org.ragdollcat.first.model.entity.User;
import org.ragdollcat.first.model.enums.SpaceRoleEnum;
import org.ragdollcat.first.model.enums.SpaceTypeEnum;
import org.ragdollcat.first.service.PictureService;
import org.ragdollcat.first.service.SpaceService;
import org.ragdollcat.first.service.SpaceUserService;
import org.ragdollcat.first.service.UserService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 自定义权限加载接口实现类
 */
@Component    // 保证此类被 SpringBoot 扫描，完成 Sa-Token 的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {

    @Resource
    private SpaceUserAuthManager spaceUserAuthManager;

    @Resource
    private SpaceUserService spaceUserService;

    @Resource
    private SpaceService spaceService;

    @Resource
    private PictureService pictureService;

    @Resource
    private UserService userService;

    /**
     * 返回一个账号所拥有的权限码集合
     * 浏览者，编辑者，管理员是团队空间的权限，和用户体系的普通用户，管理员是两套不同的
     * 浏览者viewer的权限：查看图片
     * 编辑者editor的权限：查看图片、上传图片、修改图片、删除图片
     * 管理者admin的权限：成员管理、查看图片、上传图片、修改图片、删除图片
     *
     * @param loginId   账号id，即你在调用 StpUtil.login(id) 时写入的标识值。
     * @param loginType 账号体系标识
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        //仅仅对Space进行校验
        if (!StpKit.SPACE_TYPE.equals(loginType)) {
            return new ArrayList<>();
        }
        //获取管理员权限列表：成员管理、查看图片、上传图片、修改图片、删除图片
        List<String> adminPremession = spaceUserAuthManager.getPermessionsByRole(SpaceRoleEnum.ADMIN.getValue());
        //获取浏览者viewer的权限：查看图片
        List<String> viewerPremession = spaceUserAuthManager.getPermessionsByRole(SpaceRoleEnum.VIEWER.getValue());
        //获取编辑者editor的权限：查看图片、上传图片、修改图片、删除图片
        List<String> editorPremession = spaceUserAuthManager.getPermessionsByRole(SpaceRoleEnum.EDITOR.getValue());


        //获取当前请求的类型
        SpaceUserAuthContext authContextByRequest = spaceUserAuthManager.getAuthContextByRequest();

        if (ObjUtil.isEmpty(authContextByRequest)) {
            return new ArrayList<>();
        }
        //如果所有字段都为空，视为公共图库
        if (allFieldIsNull(authContextByRequest)) {
            return adminPremession;
        }
        User user = (User) StpKit.SPACE.getSessionByLoginId(loginId).get(UserConstant.USER_LOGIN_STATE);
        ThrowUtils.throwIf(ObjUtil.isEmpty(user), ErrorCode.NO_AUTH_ERROR, "请先登录！");

        //分类判断
        //图片ID（来自图片Controller）
        Long pictureId = authContextByRequest.getPictureId();
        //空间ID（来自空间Controller）
        Long spaceId = authContextByRequest.getSpaceId();
        //图片用户ID（来自图片用户Controller）
        Long spaceUserId = authContextByRequest.getSpaceUserId();

        //图片用户ID不为空，则查出图片用户表对应ID的用户的角色，再用该角色查询其权限
        if (ObjUtil.isNotEmpty(spaceUserId)) {
            SpaceUser spaceUser = spaceUserService.getById(spaceUserId);
            ThrowUtils.throwIf(ObjUtil.isEmpty(spaceUser), ErrorCode.OPERATION_ERROR, "该空间用户不存在！");
            //查询当前用户是否是该团队空间的管理员
            if (spaceUserService.lambdaQuery().
                    eq(SpaceUser::getUserId,user.getId()).
                    eq(SpaceUser::getSpaceId,spaceUser.getSpaceId()).
                    eq(SpaceUser::getSpaceRole,SpaceRoleEnum.ADMIN.getValue()).exists()){
                return adminPremession;
            }
            return viewerPremession;
        }

        //空间ID不为空
        if (ObjUtil.isNotEmpty(spaceId)) {
            return handlerSpace(spaceId, user, viewerPremession, editorPremession);
        }

        //图片ID不为空
        if (ObjUtil.isNotEmpty(pictureId)) {
            //根据图片ID查spaceId
            Picture picture = pictureService.getById(pictureId);
            ThrowUtils.throwIf(ObjUtil.isEmpty(picture), ErrorCode.OPERATION_ERROR, "该图片不存在！");
            Long pictureTableSpaceId = picture.getSpaceId();
            //如果为空，就是公共图库,只有自己或管理员才能操作
            if (ObjUtil.isEmpty(pictureTableSpaceId)) {
                if (picture.getUserId().equals(user.getId()) || userService.isAdmin(user)) {
                    return editorPremession;
                }
                //否则只能查看
                return viewerPremession;
            }
            //不为空，还需要根据spaceId判断是私有图库还是团队空间
            return handlerSpace(pictureTableSpaceId, user, viewerPremession, editorPremession);
        }
        return new ArrayList<>();
    }

    /**
     * 空间类别区分以及权限校验
     * @param spaceId
     * @param user
     * @param viewerPremession
     * @param editorPremession
     * @return
     */
    private List<String> handlerSpace(Long spaceId, User user, List<String> viewerPremession, List<String> editorPremession) {
        //则需要先区分是私有空间还是团队空间
        Space space = spaceService.getById(spaceId);
        ThrowUtils.throwIf(ObjUtil.isEmpty(space), ErrorCode.OPERATION_ERROR, "该空间不存在！");
        Integer spaceType = space.getSpaceType();
        //如果是私有空间
        if (spaceType.equals(SpaceTypeEnum.PRIVATE.getValue())) {
            //需要判断当前登录人是否是本空间的所有者
            //不是则只有查看权限
            if (!user.getId().equals(space.getUserId())) {
                return viewerPremession;
            }
            //否则是编辑者的权限（私有空间不涉及管理员的成员管理）
            return editorPremession;
        }
        //如果是团队空间，查用户空间表,返回该用户在用户空间表对应角色的权限
        QueryWrapper<SpaceUser> spaceUserQueryWrapper = new QueryWrapper<>();
        spaceUserQueryWrapper.eq("spaceId", space.getId());
        spaceUserQueryWrapper.eq("userId", user.getId());
        SpaceUser spaceUser = spaceUserService.getOne(spaceUserQueryWrapper);
        ThrowUtils.throwIf(ObjUtil.isEmpty(spaceUser), ErrorCode.OPERATION_ERROR, "该空间用户不存在！");
        String spaceRole = spaceUser.getSpaceRole();
        return spaceUserAuthManager.getPermessionsByRole(spaceRole);
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        // 本 list 仅做模拟，实际项目中要根据具体业务逻辑来查询角色
        return new ArrayList<String>();
    }


    private boolean allFieldIsNull(Object object) {
        if (ObjUtil.isEmpty(object)) {
            return true;
        }
        return Arrays.stream(ReflectUtil.getFields(object.getClass())).map(field -> ReflectUtil.getFieldValue(object, field)).allMatch(ObjectUtil::isEmpty);
    }


}
